package
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.events.EventDispatcher;
	
	import mx.collections.ArrayCollection;
	import mx.events.CollectionEvent;
	
	import org.casalib.events.ListenerManager;
	import org.casalib.events.ProcessEvent;
	
	public class Photo extends EventDispatcher
	{
		public function get id():int {
			return _id;
		}
		
		public function set id(id:int):void {
			_id = id;
		}
		
		public function get image():Bitmap {
			return _image;
		}
		
		public function get original():Bitmap {
			return _original;
		}
		
		/**
		 * After you made changes to it, remember to call renderEffects().
		 */
		[Bindable]
		public var effects:ArrayCollection = new ArrayCollection();
		
		public function get dateCreated():Date{
			return _dateCreated;
		}
		
		[Bindable]
		public var tags:ArrayCollection = new ArrayCollection();
		
		
		/**
		 * Constructor.
		 */ 
		public function Photo(image:Bitmap, dateCreated:Date = null)
		{
			_original = new Bitmap(image.bitmapData.clone());
			_image = new Bitmap(image.bitmapData.clone());
			if (dateCreated != null) {
				_dateCreated = dateCreated;
			}
			
			_listenerManager = ListenerManager.getManager(this);
		}
		
		public function renderEffects(evt:CollectionEvent = null, index:uint = 0):void{
			if (index == 0){
				_effectApplyProgress = 0;
				_image.bitmapData.dispose();
				_image = new Bitmap(_original.bitmapData.clone());
			}
			
			if (_effectApplyProgress<effects.length){
				effects.getItemAt(_effectApplyProgress).applyOn(_image,
					function(rimage:Bitmap):void{
						_image = rimage;
						_effectApplyProgress++;
						renderEffects(null,_effectApplyProgress);
					}
				);
			} else {
				if(effects.length == 0){
					_image.bitmapData.dispose();
					_image = new Bitmap(_original.bitmapData.clone());
				}
				dispatchEvent(new ProcessEvent(ProcessEvent.COMPLETE));
			}	
		}
		
		public function getThumbnail():Bitmap {
			var tn:Bitmap = new Bitmap(_image.bitmapData.clone());
			return tn;
		}
		
		/**
		 * Set the result image directly.<br />
		 * It is mainly used for restoring Photo from the database.
		 */
		public function setCachedImage(img:Bitmap):void {
			_image = img;
		}
		
		/**
			@exclude
		*/
		override public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void {
			super.addEventListener(type, listener, useCapture, priority, useWeakReference);
			this._listenerManager.addEventListener(type, listener, useCapture, priority, useWeakReference);
		}
		
		/**
			@exclude
		*/
		override public function removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void {
			super.removeEventListener(type, listener, useCapture);
			this._listenerManager.removeEventListener(type, listener, useCapture);
		}
		
		public function removeEventsForType(type:String):void {
			this._listenerManager.removeEventsForType(type);
		}
		
		public function removeEventsForListener(listener:Function):void {
			this._listenerManager.removeEventsForListener(listener);
		}
		
		public function removeEventListeners():void {
			this._listenerManager.removeEventListeners();
		}
		
		/**
		 * Call this to release it from memory.
		 */
		public function dispose():void {
			removeEventListeners();
			_listenerManager.destroy();
			
			if (_image.bitmapData)
				_image.bitmapData.dispose();
			if (_original.bitmapData)
				_original.bitmapData.dispose();
		}
		
		//private stuff
		[Bindable]
		private var _id:int = -1;
		
		[Bindable]
		private var _image:Bitmap;
		
		private var _original:Bitmap;
		
		[Bindable]
		private var _dateCreated:Date = new Date();
		
		private var _effectApplyProgress:uint = 0;
		
		private var _listenerManager:ListenerManager;
	}
}